﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using Newtonsoft.Json;
using System.IO;
using System.Xml;
using System.Xml.Serialization;

namespace aPCSuite
{
    public delegate void DeletegateAddListItem(ListViewItem lvi);
    public partial class Form1 : Form
    {
        
        public DeletegateAddListItem m_DelegateAddListItem;
        private SMSItems items = null;
        private List<string> items_detail = new List<string>();
        public static string mobile_code = "";
        private Transaction _transaction;
        private Form5 form5 = null;
        private Thread _request = null;
        private Dictionary<string, string> address_list = null;
        private Command _command = null; 

        public Form1()
        {
            InitializeComponent();

            txtCode.Font = new Font(txtCode.Font.Name, 12);

            Font ft = new Font(listView1.Font.Name, 10);
            listView1.Font = ft;
            listView2.Font = ft;

            aPCSuite.Properties.Settings set = aPCSuite.Properties.Settings.Default;
            if (set.dev_code != "")
                txtCode.Text = set.dev_code;

            ImageList imageList = new ImageList();
            imageList.ImageSize = new Size(5, 5);
            imageList.Images.Add(Image.FromFile(@"sicon.png"));
            listView1.SmallImageList = imageList;
            m_DelegateAddListItem = new DeletegateAddListItem(this.AddListItem);
            // Create thread for send request and get response from server
            btnRefresh_Click(null, null);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Form2 form2 = new Form2();
            form2.ShowDialog();
        }

        private void btnFake_Click(object sender, EventArgs e)
        {
            Form3 form3 = new Form3();
            form3.ShowDialog();
        }

        private void btnReply_Click(object sender, EventArgs e)
        {
            Form4 form4 = new Form4();
            if (listView1.SelectedItems.Count > 0)
            {
                List<string> list = new List<string>(items.group_list.Keys);
                string key = list[listView1.SelectedItems[0].Index];
                SMSGroup group = items.GetGroup(key);
                if (group != null)
                    form4.SetReplyAddress(group.address);
            }
            form4.ShowDialog();
        }

        private string BuildRequest(REQ_CMD cmd)
        {
            string xml = "";
            switch (cmd)
            {
                case REQ_CMD.SMS_LIST:
                    xml = "<protocol encoding=\"UTF-8\" version=\"1.0\">";
                    xml += "<app_id>1</app_id>";
                    xml += "<sms_list>";
                    xml += "<dev_code>" + aPCSuite.Properties.Settings.Default.dev_code + "</dev_code>";
                    xml += "<limit>-1</limit>";
                    xml += "</sms_list>";
                    xml += "</protocol>";
                    break;

                case REQ_CMD.FETCH_RESULT:
                    xml = "<protocol encoding=\"UTF-8\" version=\"1.0\">";
                    xml += "<app_id>1</app_id>";
                    xml += "<fetch>";
                    xml += "<dev_code>" + aPCSuite.Properties.Settings.Default.dev_code + "</dev_code>";
                    xml += "</fetch>";
                    xml += "</protocol>";
                    break;

                case REQ_CMD.SMS_DELETE:
                    break;
            }
            return xml;
        }

        private void ShowProgressDialog()
        {
            this.Invoke(new MethodInvoker(delegate
                {
                    form5 = new Form5();
                    form5._close_event += new close_event(_close_event);
                    form5.SetProgressStatus("Processing...");
                    form5.ShowDialog();
                }));
        }

        private void _close_event(object sender, EventArgs e)
        {
            stop_request();
            if (_transaction != null)
                Transaction.post_trasn_result(_transaction.trans_id, 1);
            // close transaction
            close_trans();
        }

        private void CloseProgressDialog(int status)
        {
            this.Invoke(new MethodInvoker(delegate
            {
                if (form5 != null)
                {
                    if (status == 0)
                        form5.SetProgressStatus("Successful");
                    else
                        form5.SetProgressStatus("Failed");
                    Thread.Sleep(2000);
                    form5.Close();
                }
            }));
        }

        private void request_handler()
        {
            try
            {
                Console.WriteLine("request_handler");
                string req = BuildRequest(_command.req_cmd);
                HttpRequestResponse request = new HttpRequestResponse(req, Transaction.uri);
                string res = request.SendRequest();

                if (res != "")
                {
                    // XML response: Deserialize XML string to object
                    using (TextReader reader = new StringReader(res))
                    {
                        XmlSerializer serializer = new XmlSerializer(typeof(protocol));
                        protocol ret = (protocol)serializer.Deserialize(reader);
                        Console.WriteLine("ret");

                        if (Transaction.CodeOk(ret.code))
                        {
                            // start thread to fetch result
                            _transaction = new Transaction();
                            _transaction.trans_id = ret.trans_id;
                            _transaction.cmd = REQ_CMD.FETCH_RESULT;
                            _transaction.callback = new WaitCallback(this.callback);
                            _transaction.StartFetch();
                        }
                        else
                        {
                            CloseProgressDialog(1);
                            Transaction.post_trasn_result(ret.trans_id, 1);
                        }
                    }
                }
                else
                    CloseProgressDialog(1);
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("request_handler exception : {0}", ex.Message);
            }
        }

        public void Request_Handler(object state)
        {
            try
            {
                stop_request();
                close_trans();
                _request = new Thread(new ThreadStart(request_handler));
                _request.Start();
                Thread.Sleep(100);
                ShowProgressDialog();
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("Request_Handler exception : {0}", ex.Message);
            }
        }

        private void ShowSMS(SMSItems items)
        {
            if (items != null)
            {
                // clear list view
                this.Invoke(new MethodInvoker(delegate
                    { listView1.Items.Clear(); }));
                foreach (KeyValuePair<string,SMSGroup> item in items.group_list)
                {
                    int count = item.Value.sms_list.Count;

                    var enumerator = item.Value.sms_list.Values.GetEnumerator();
                    enumerator.MoveNext();
                    sms _sms = enumerator.Current;

                    //sms _sms = item.Value.sms_list[count - 1];
                    ListViewItem lvi = new ListViewItem();
                    string address = (_sms.from != "" ? _sms.from : _sms.to);
                    lvi.SubItems.Add(address);
                    lvi.SubItems.Add(count.ToString());
                    lvi.SubItems.Add(_sms.content);
                    lvi.SubItems.Add(_sms.create_date);
                    if (item.Value.status == "N")
                        lvi.ImageIndex = 0;
                    this.Invoke(m_DelegateAddListItem, new object[] { lvi });
                }
            }
        }

        private void AddListItem(ListViewItem lvi)
        {
            listView1.Items.Add(lvi);
        }

        private void listView1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (listView1.SelectedItems.Count > 0)
            {
                List<string> list = new List<string>(items.group_list.Keys);
                string key = list[listView1.SelectedItems[0].Index];
                SMSGroup group = items.GetGroup(key);
                Console.WriteLine("Selected index : {0}", listView1.SelectedItems[0].Index);
                // Show group detail
                if (group != null)
                {
                    // clear list view
                    listView2.Items.Clear();
                    /*foreach (sms _sms in group.sms_list)
                    {
                        string address = (_sms.type == 2 ? "Me" : _sms.from);
                        ListViewItem lvi = new ListViewItem(address);
                        lvi.SubItems.Add(_sms.content);
                        lvi.SubItems.Add(_sms.create_date);
                        listView2.Items.Add(lvi);
                    }/**/
                    foreach (KeyValuePair<string, sms> item in group.sms_list)
                    {
                        sms _sms = item.Value;
                        string address = (_sms.type == 2 ? "Me" : _sms.from);
                        ListViewItem lvi = new ListViewItem(address);
                        lvi.SubItems.Add(_sms.content);
                        lvi.SubItems.Add(_sms.create_date);
                        listView2.Items.Add(lvi);
                    }
                }
            }
        }

        private void GroupSMS(sms_list _sms_list)
        {
            
            items = new SMSItems();
            address_list = new Dictionary<string, string>();
            // group sms
            for (int i = 0; i < _sms_list.arr_sms.Length; ++i)
            {
                sms _sms = _sms_list.arr_sms[i];
                // find group
                SMSGroup sms_group = items.GetGroup(_sms.thread_id);
                if (sms_group == null)
                {
                    sms_group = new SMSGroup();
                   
                    sms_group.thread_id = _sms.thread_id;
                    sms_group.address = (_sms.from != "" ? _sms.from : _sms.to);

                    items.Add(_sms.thread_id, sms_group);

                    // make address list
                    address_list.Add(sms_group.thread_id, sms_group.address);
                }
                    
                if (_sms.status == "N")
                    sms_group.status = _sms.status;
                if (sms_group.address == "")
                    sms_group.address = (_sms.from != "" ? _sms.from : _sms.to);

                if (address_list[sms_group.thread_id] == "")
                    address_list[sms_group.thread_id] = "";

                //_sms.create_date = Transaction.ConvertUtcToLocalDateTime(_sms.create_date);

                //sms_group.Add(_sms);
                sms_group.Add(_sms.id.ToString(), _sms);
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            if (txtCode.Text.Length > 0)
            {
                if(_transaction != null)
                    _transaction.StopFetch();

                _command = new Command(REQ_CMD.SMS_LIST);
                ThreadPool.QueueUserWorkItem(new WaitCallback(Request_Handler), _command);
            }
        }

        private void callback(object sender)
        {
            try
            {
                protocol ret = sender as protocol;
                if (ret != null)
                {
                    if (ret.trans_id == _transaction.trans_id)
                    {
                        if (ret.code == Transaction.OK)
                        {
                            CloseProgressDialog(0);
                            if (ret._sms_list != null)
                            {
                                GroupSMS(ret._sms_list);
                                ShowSMS(items);
                            }
                            else
                            {
                                // deleted sms
                            }
                            Transaction.post_trasn_result(ret.trans_id, 0);
                        }
                        else if (!Transaction.CodeOk(ret.code))
                        {
                            CloseProgressDialog(1);
                            Transaction.post_trasn_result(ret.trans_id, 1);
                        }
                    }
                    else
                    {
                        CloseProgressDialog(1);
                        Transaction.post_trasn_result(ret.trans_id, 1);
                    }
                }
                else
                {
                    CloseProgressDialog(1);
                }
            }
            catch (System.Exception ex)
            {
                Console.WriteLine("Callback exception : {0}", ex.Message);
            }
        }

        private void txtCode_Leave(object sender, EventArgs e)
        {
            aPCSuite.Properties.Settings set = aPCSuite.Properties.Settings.Default;
            set.dev_code = txtCode.Text;
            set.Save();
        }

        private void stop_request()
        {
            if (_request != null)
            {
                _request.Abort();
                _request.Join();
            }
        }

        private void close_trans()
        {
            if (_transaction != null)
                _transaction.StopFetch();
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            stop_request();
            close_trans();
        }

        private void listView2_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Delete)
            {
                if (listView2.SelectedItems.Count > 0)
                {
                    DialogResult result1 = MessageBox.Show("Do you want to delete this message?",
                        "Confirm",
                        MessageBoxButtons.YesNo);
                    if (result1 == DialogResult.Yes)
                    {
                        // Delete object
                        _command = new Command(REQ_CMD.SMS_DELETE);
                        //ThreadPool.QueueUserWorkItem(new WaitCallback(Request_Handler), _command);
                    }
            
                }
            }
        }
    }
}
